﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Casamiel.Domain.Entity;

using Casamiel.Domain.Request;
using Casamiel.Domain.Request.IC;
using Casamiel.Domain.Response;
using Casamiel.Domain.Response.IC;
using Casamiel.Domain.Response.Waimai;
using MediatR;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Casamiel.Application.Commands.Waimai
{
	/// <summary>
	/// 外卖下单预览
	/// </summary>
    public sealed class OrderPreviewCommandHandler : BaseCommandHandler, IRequestHandler<OrderPreviewCommand, BaseResult<OrderPreviewReponse>>
    {
		private readonly IMbrStoreRepository _mbrStoreRepository;
		private readonly IMemberCouponRepository _memberCouponRepository;
		private readonly IMemberRepository _memberRepository;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="netICService"></param>
		/// <param name="httpClientFactory"></param>
		/// <param name="settings"></param>
		/// <param name="mbrStoreRepository"></param>
		/// <param name="memberCouponRepository"></param>
		/// <param name="memberRepository"></param>
		public OrderPreviewCommandHandler(INetICService netICService, IHttpClientFactory httpClientFactory, IOptionsSnapshot<CasamielSettings> settings,
			IMbrStoreRepository mbrStoreRepository, IMemberCouponRepository memberCouponRepository, IMemberRepository memberRepository

		) : base(netICService, httpClientFactory, settings)
        {
			_mbrStoreRepository = mbrStoreRepository;
			_memberCouponRepository = memberCouponRepository;
			_memberRepository = memberRepository;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<BaseResult<OrderPreviewReponse>> Handle(OrderPreviewCommand request, CancellationToken cancellationToken)
        {
			var Discount = 0m;

			if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
			
			
			var rsp = new OrderPreviewReponse
            {
                Discount = 0,
                FreightMoney = 0
            };
            if (request.OrderPreview == null)
            {
                LoggerSystemErrorInfo.Error($"OrderPreviewCommandHandler");
                return new BaseResult<OrderPreviewReponse>(null, 9999, "出错了");
            }
            if (request.OrderPreview.GoodsList == null || !request.OrderPreview.GoodsList.Any())
            {
                return new BaseResult<OrderPreviewReponse>(null, 9999, "产品不能空");
            }
			var rebate = 0m;

			var OrderAmount = request.OrderPreview.GoodsList.Sum(a => a.Price * a.GoodsQuantity);
			//if (this.Casasettings.ApiName == "casamielnetwork") {
				//if (DateTime.Now.Month > 8 || request.Mobile == "18069849152" || request.Mobile == "18726171085" || request.Mobile == "17342063609") {
				//	if (OrderAmount >= 40) {
				//		rebate = 5;
				//		rsp.Discount = 5;
				//	}
				//}
			//}
            
            
            if (request.OrderPreview.OrderType > 1)
            {
                rsp.FreightMoney = await CalculateWaimaiOrderFreightMoney(OrderAmount).ConfigureAwait(false);
            }
			
			if (request.OrderPreview.StoreId == 0) {
				return new BaseResult<OrderPreviewReponse>(rsp, 0, "");
			}

			var entity = await _memberRepository.FindAsync<ICasaMielSession>(request.Mobile).ConfigureAwait(false);
			if (entity == null) {
				return new BaseResult<OrderPreviewReponse>(null, 9999, "会员不存在");
			}
			var storeInfo = await _mbrStoreRepository.GetByStoreIdAsync<ICasaMielSession>(request.OrderPreview.StoreId).ConfigureAwait(false);
			if (storeInfo == null && request.OrderPreview.DiscountList.Any()) {
				return new BaseResult<OrderPreviewReponse>(null, 9999, "门店信息有误");
			}
			if (request.OrderPreview.DiscountList != null && request.OrderPreview.DiscountList.Any()) {
				decimal ticketInfoPrice;
				ICResult ticketLimit;
				if (request.OrderPreview.DiscountList.Count > 1) {
					return new BaseResult<OrderPreviewReponse>(null, 9999, "券只能用一张");
				}
				if (request.OrderPreview.DiscountList[0].DiscountCouponType == 1) {
					 
					var ticketreq = new GetTicticketReq { Cardno = request.OrderPreview.DiscountList[0].CardNo, Pagesize = 200, State = 2, Pageindex = 1 };
					Iclogger.Trace($"GeticticketReq:{JsonConvert.SerializeObject(ticketreq)}");
					var a = await NetICService.Geticticket(ticketreq).ConfigureAwait(false);
					if (a.code == 0) {
						var list = JsonConvert.DeserializeObject<TicketItemRoot>(a.content);
						var ticket = list.Tickets.SingleOrDefault(t => t.Ticketid == request.OrderPreview.DiscountList[0].DiscountCouponId);
						if (ticket != null) {
							request.OrderPreview.DiscountList[0].DiscountCouponMoney = ticket.Je.ToDecimal(0);
							ticketInfoPrice = request.OrderPreview.DiscountList[0].DiscountCouponMoney;
							Discount = ticketInfoPrice;
						} else {
							return new BaseResult<OrderPreviewReponse>(null, -23, "优惠券不可用");
						}

					} else {
						return new BaseResult<OrderPreviewReponse>(null, -23, "优惠券不可用");
					}
					var tt = new List<long>() { request.OrderPreview.DiscountList[0].DiscountCouponId };
					ticketLimit = await NetICService.TicketLimit(storeInfo.RelationId, tt, 1, true).ConfigureAwait(false);
				} else if (request.OrderPreview.DiscountList[0].DiscountCouponType == 2) {
					var memberCoupon = await _memberCouponRepository.GetKeyAsync<ICasaMielSession>(request.OrderPreview.DiscountList[0].DiscountCouponId).ConfigureAwait(false);
					if (memberCoupon == null || memberCoupon.MID != entity.ID) {
						return new BaseResult<OrderPreviewReponse>(null, 9999, "券不存在");
					}
					 
					var ticketInfoRsp = await NetICService.Tmticketquery(new Domain.Request.IC.TmticketqueryReq { ticketcode = memberCoupon.Ticketcode }).ConfigureAwait(false);
					if (ticketInfoRsp.code != 0) {

						return new BaseResult<OrderPreviewReponse>(null, ticketInfoRsp.code, ticketInfoRsp.msg);

					}
					var ticketInfo = JObject.Parse(ticketInfoRsp.content);

					ticketInfoPrice = memberCoupon.Price;

					//a.Productname = ticketInfo["productname"].ToString();
					//a.Productid = ticketInfo["productid"].ToInt64(0);
					var State = ticketInfo["state"].ToInt16(0);
					//a.Startdate = DateTime.Parse(ticketInfo["startdate"].ToString(), CultureInfo.InvariantCulture);
					//a.Enddate = DateTime.Parse(ticketInfo["enddate"].ToString(), CultureInfo.InvariantCulture);
					if (State != 3) {
						return new BaseResult<OrderPreviewReponse>(null, 9999, "券不可用");
					}
					var ids = new List<long> {
								ticketInfo["productid"].ToInt64(0)
							};
					ticketLimit = await NetICService.TicketLimit(storeInfo.RelationId, ids, 0, false).ConfigureAwait(false);
					//ticketLimit = await NetICService.TicketLimit(storeInfo.RelationId, memberCoupon.Ticketcode).ConfigureAwait(false);
				} else {
					return new BaseResult<OrderPreviewReponse>(null, 9999, "券类型有误");
				}
				var rule = JsonConvert.DeserializeObject<TicketsRules>(ticketLimit.content);
				//51、当前券要求最低的单据金额，limitvalue为单据金额
				//21、券仅允许消费的产品，limitvalue 为限制的产品标识
				//215、券必须消费的产品，limitvalue 为限制的产品标识
				//216、券需要消费的产品(之一)，limitvalue 为限制的产品标识，和 215 不同，216 只需要有一种产品就可以了，如果 limitvalue 只有一种产品，则和 215 效果相同
				//22、券不允许消费的产品，limitvalue 为限制的产品标识
				Discount = ticketInfoPrice;
				var list216 = rule.Tickets.Where(c => c.Limittype == 216);
				if (list216.Any()) {
					bool s = false;
					var list216msg = "";
					foreach (var item in list216) {
						var ss = request.OrderPreview.GoodsList.Count(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture));
						if (ss > 0) {
							s = true;
						} else {
							list216msg += $"{item.Productname}{item.Limitdesc}";
						}
					}
					if (!s) {
						//list.Tickets[i].State = 0;
						return new BaseResult<OrderPreviewReponse>(null, 9999, list216msg);
					}
					Discount = ticketInfoPrice;
				}

				var list215 = rule.Tickets.Where(c => c.Limittype == 215);
				if (list215.Any()) {
					var list215sucess = true;
					var amsg = "";
					foreach (var item in list215) {
						if (!request.OrderPreview.GoodsList.Any(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture))) {
							amsg += $"{item.Productname}{item.Limitdesc}";
							list215sucess = false;
						}
					}
					if (!list215sucess) {
						//list.Tickets[i].State = 0;
						return new BaseResult<OrderPreviewReponse>(null, 9999, amsg);
					}
					//Discount = ticketInfoPrice;
				}
				var abc = rule.Tickets;
				foreach (var item in abc) {
					if (item.Limittype == 51) {
						var tamount = OrderAmount;

						if (tamount < item.Limitvalue.ToDecimal(0)) {
							//list.Tickets[i].State = 0;
							return new BaseResult<OrderPreviewReponse>(null, 9999, item.Limitdesc);
						}
						//Discount = ticketInfoPrice;
					}
					if (item.Limittype == 21) {
						var aa = request.OrderPreview.GoodsList.Where(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture)).ToList();
						if (aa.Any()) {
							//list.Tickets[i].State = 0;
							return new BaseResult<OrderPreviewReponse>(null, 9999, item.Limitdesc);
						}
						//Discount = aa[0].Price;
					}
					if (item.Limittype == 22) {
						var aa = request.OrderPreview.GoodsList.Count(c => c.GoodsRelationId == int.Parse(item.Limitvalue, System.Globalization.CultureInfo.CurrentCulture));
						if (aa > 0) {
							//list.Tickets[i].State = 0;
							return new BaseResult<OrderPreviewReponse>(null, 9999, item.Limitdesc);
						}
						Discount = ticketInfoPrice;
					}
				}
			}
			var paymoney = OrderAmount - rebate - Discount + rsp.FreightMoney;
			if (this.Casasettings.ApiName == "doncoApi") {
				paymoney = OrderAmount - Discount;
				if (paymoney < 0) {
					paymoney = rsp.FreightMoney;
				} else {
					paymoney += rsp.FreightMoney;
				}
			}
			rsp.OrderAmount = OrderAmount;
			rsp.PayAmount = paymoney;
			return new BaseResult<OrderPreviewReponse>(rsp, 0, "");
        }
    }
}
